#include "../include/GameManager.hh"
#include "../include/Dungeon.hh"
#include "../include/Character.hh"
#include "../include/Skill.hh"
#include <iostream>
#include <cstdlib>
#include <limits>
#include <memory>

GameManager::GameManager() : running(true) {
    // Initialize character: Berserker
    availableCharacters.push_back(std::make_unique<Character>("Berserker", "The Berserker has the most balanced combat and defensive abilities. He can deal more damage at the cost of his own health! The more monsters the Berserker defeats, the higher his attack power becomes!"));
    availableCharacters.back()->attributes.health = 100;
    availableCharacters.back()->maxHealth = 100; // Set maxHealth
    availableCharacters.back()->attributes.attack = 100;
    availableCharacters.back()->attributes.defense = 10;
    availableCharacters.back()->attributes.speed = 10;
    availableCharacters.back()->attributes.critChance = 20;
    availableCharacters.back()->attributes.critDamage = 50;
    availableCharacters.back()->attributes.armor = 5;
    availableCharacters.back()->attributes.penetration = 5;
    availableCharacters.back()->attributes.damageMultiplier = 1.0f;

    // Initialize character: Mage
    availableCharacters.push_back(std::make_unique<Character>("Mage", "The Mage has the strongest control and sustained damage abilities, and can significantly restore his own health, but has relatively low health and defense. Don't worry, the Mage's core treasure will prevent one death!"));
    availableCharacters.back()->attributes.health = 40;
    availableCharacters.back()->maxHealth = 40; // Set maxHealth
    availableCharacters.back()->attributes.attack = 110;
    availableCharacters.back()->attributes.defense = 8;
    availableCharacters.back()->attributes.speed = 12;
    availableCharacters.back()->attributes.critChance = 5;
    availableCharacters.back()->attributes.critDamage = 30;
    availableCharacters.back()->attributes.armor = 3;
    availableCharacters.back()->attributes.penetration = 10;
    availableCharacters.back()->attributes.damageMultiplier = 1.0f;

    // Initialize character: Assassin
    availableCharacters.push_back(std::make_unique<Character>("Assassin", "The Assassin has the most powerful burst damage capabilities. His skills have a chance to instantly kill the enemy! He strikes without a trace, always acting first to release skills!"));
    availableCharacters.back()->attributes.health = 70;
    availableCharacters.back()->maxHealth = 70; // Set maxHealth
    availableCharacters.back()->attributes.attack = 50;
    availableCharacters.back()->attributes.defense = 9;
    availableCharacters.back()->attributes.speed = 10000000;
    availableCharacters.back()->attributes.critChance = 30;
    availableCharacters.back()->attributes.critDamage = 70;
    availableCharacters.back()->attributes.armor = 4;
    availableCharacters.back()->attributes.penetration = 8;
    availableCharacters.back()->attributes.damageMultiplier = 1.0f;

    std::cout << "Initialized " << availableCharacters.size() << " characters\n";
}

void GameManager::run() {
    try {
        showWelcomeScreen();
        showMainMenu();
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
    } catch (...) {
        std::cerr << "Unknown exception\n";
    }
}

void GameManager::showWelcomeScreen() {
    std::cout << "Entering showWelcomeScreen\n";
    system("clear");
    std::cout << "==============================\n";
    std::cout << "       Welcome to Soul Knight\n";
    std::cout << "==============================\n";
    std::cout << "Press Enter to start the game...\n";
    std::cin.get();
    // Clear input buffer
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cout << "Leaving showWelcomeScreen\n";
}

void GameManager::showMainMenu() {
    std::cout << "Entering showMainMenu\n";
    while (running) {
        std::cout << "Main menu loop starting\n";
        system("clear");
        std::cout << "==== Main Menu ====\n";
        std::cout << "1. Start Game\n";
        std::cout << "2. Exit Game\n";
        std::cout << "Enter your choice (1-2): ";
        int choice = getValidInput(1, 2);
        std::cout << "Received input " << choice << "\n";
        handleMenuChoice(choice);
    }
    std::cout << "Leaving showMainMenu\n";
}

void GameManager::handleMenuChoice(int choice) {
    switch (choice) {
        case 1:
            startGame();
            break;
        case 2:
            running = false;
            system("clear");
            std::cout << "Exiting game...\n";
            break;
    }
}

void GameManager::startGame() {
    selectCharacter();
    if (player) {
        enterDungeon();
    } else {
        std::cout << "Character selection failed, cannot start game.\n";
        waitForKey();
    }
}

void GameManager::selectCharacter() {
    system("clear");
    std::cout << "=== Select Your Character ===\n";
    for (size_t i = 0; i < availableCharacters.size(); ++i) {
        std::cout << i + 1 << ". " << availableCharacters[i]->name
                  << ": " << availableCharacters[i]->description << "\n\n";
    }
    std::cout << "Enter your choice (1-" << availableCharacters.size() << "): ";
    int choice = getValidInput(1, static_cast<int>(availableCharacters.size()));

    player = std::make_unique<Character>(availableCharacters[choice - 1]->name,
                                        availableCharacters[choice - 1]->description);
    player->attributes = availableCharacters[choice - 1]->attributes;
    player->maxHealth = availableCharacters[choice - 1]->maxHealth; // Copy maxHealth

    // Assign skills based on character name
    if (player->name == "Berserker") {
        player->addSkill(create(SkillType::BloodAttack));
        player->addSkill(create(SkillType::DevastatingStrike));
        player->addSkill(create(SkillType::Heal));
    } else if (player->name == "Mage") {
        player->addSkill(create(SkillType::ThunderBird));
        player->addSkill(create(SkillType::GreatFireball));
        player->addSkill(create(SkillType::HundredHeal));
    } else if (player->name == "Assassin") {
        player->addSkill(create(SkillType::AssaultPierce));
        player->addSkill(create(SkillType::BleedingWound));
        player->addSkill(create(SkillType::SoulInfiltration));
    } else {
        std::cout << "Warning: Unknown character " << player->name << ", no skills assigned\n";
    }

    system("clear");
    std::cout << "You selected " << player->name << "!\n";
    player->displayInfo();
    std::cout << "Character " << player->name << " selection completed, skill count: " << player->skills.size() << "\n";
    std::cout << "Press Enter to continue...\n";
    std::cin.get();
}

void GameManager::enterDungeon() {
    system("clear");
    std::cout << "=== You entered a mysterious dungeon ===\n";
    currentDungeon = std::make_unique<Dungeon>(3, 5, player.get());
    currentDungeon->explore();
    std::cout << "Press Enter to return to main menu...\n";
    std::cin.get();
}

void GameManager::waitForKey() {
    std::cin.get();
}

int GameManager::getValidInput(int min, int max) {
    int input;
    while (true) {
        std::cout << "> ";
        if (std::cin >> input && input >= min && input <= max) {
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            return input;
        }
        std::cout << "Invalid input, please enter a number between " << min << " and " << max << ".\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

GameManager::~GameManager() = default;